﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Web;
using System.Web.Mvc;

namespace ASP.NET_MVC_3_Sample.Controllers
{
    public class HomeController : AsyncController
    {
        public ActionResult Index()
        {
            return View();
        }

        /// <summary>
        /// Starts long running task.
        /// </summary>
        public void FindAnswerAsync(string question)
        {
            var getAnswer = new AsyncFunc<string, string>(GetAnswer);
            
            getAnswer.Completed += (s, e) =>
            {
                // Save parameters to make them available to FindAnswerCompleted
                AsyncManager.Parameters["sender"] = s;                               
                AsyncManager.Parameters["e"] = e;

                // Decrement OutstandingOperations counter to notify ASP.NET MVC
                // that the operation has completed
                AsyncManager.OutstandingOperations.Decrement();
            };

            AsyncManager.OutstandingOperations.Increment();
            getAnswer.TryInvokeAsync(question);    
        }

        /// <summary>
        /// Handles FindAnswer completion.
        /// </summary>
        /// <remarks>
        /// This method accepts both sender and event arguments to make it similar
        /// to what one would typically see with components implementing EAP.
        /// Although sender could be removed I think it is quite important to
        /// pass the argument to correctly handle any errors that could occure
        /// in the asynchronous call.
        /// </remarks>
        /// <param name="sender">Sender.</param>
        /// <param name="e">Event arguments which hold the result.</param>
        /// <returns></returns>
        public ActionResult FindAnswerCompleted(object sender, AsyncFuncCompletedEventArgs<string> e)
        {
            if (e.Error != null)
            {
                // Report exception
                ViewBag.Message = "Operation failed: " + e.Error.Message;
            }
            else if (e.Cancelled)
            {
                // Ignore
                ViewBag.Message = "Operation cancelled";
            }
            else
            {
                ViewBag.Message = "Operation succeeded";
                ViewBag.Answer = e.Result;
            }
            return View();
        }

        /// <summary>
        /// Finds the answer to any question one could ask.
        /// </summary>
        /// <param name="question">Question.</param>
        /// <returns></returns>
        private string GetAnswer(string question)
        {
            Thread.Sleep(5000);
            return "42";
        }
    }
}
